﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;

namespace ShevaEngine.Core.Modules.Graphics
{
    /// <summary>
    /// Buffers  manager.
    /// </summary>
    public class GraphicsBuffersManager
    {
        /// <summary>Singleton.</summary>
        public static readonly GraphicsBuffersManager Instance = new GraphicsBuffersManager();

        /// <summary>Vertex buffers.</summary>
        private List<VertexBuffer> VertexBuffers;
        /// <summary>Index buffers.</summary>
        private List<IndexBuffer> IndexBuffers;
        /// <summary>Graphics buffers handles.</summary>
        private List<GraphicsBuffersHandle> GraphicsBuffersHandles;

        /// <summary>VBO search.</summary>
        private Dictionary<VertexBuffer, int> VBOSearch;
        /// <summary>IBO search.</summary>
        private Dictionary<IndexBuffer, int> IBOSearch;
        /// <summary>Graphics buffers handles.</summary>
        private SortedDictionary<GraphicsBuffersHandle, int> GraphicsBuffersHandlesSearch;
               

        /// <summary>
        /// Constructor.
        /// </summary>
        private GraphicsBuffersManager()
        {
            this.VertexBuffers = new List<VertexBuffer>();
            this.IndexBuffers = new List<IndexBuffer>();
            this.GraphicsBuffersHandles = new List<GraphicsBuffersHandle>();

            this.VBOSearch = new Dictionary<VertexBuffer, int>();
            this.IBOSearch = new Dictionary<IndexBuffer, int>();
            this.GraphicsBuffersHandlesSearch = new SortedDictionary<GraphicsBuffersHandle, int>(new GraphicsBuffersHandleComparer());            
        }

        /// <summary>
        /// Method returns buffers ID.
        /// </summary>
        /// <param name="vbo"></param>
        /// <param name="ibo"></param>
        /// <returns></returns>
        public UInt16 GetBuffersID(VertexBuffer vbo, IndexBuffer ibo)
        {
            if (!this.VBOSearch.ContainsKey(vbo))
            {
                this.VBOSearch.Add(vbo, this.VertexBuffers.Count);
                this.VertexBuffers.Add(vbo);
            }

            if (!this.IBOSearch.ContainsKey(ibo))
            {
                this.IBOSearch.Add(ibo, this.IndexBuffers.Count);
                this.IndexBuffers.Add(ibo);
            }

            GraphicsBuffersHandle newHandle = new GraphicsBuffersHandle(this.VBOSearch[vbo], this.IBOSearch[ibo]);

            if (!this.GraphicsBuffersHandlesSearch.ContainsKey(newHandle))
            {
                this.GraphicsBuffersHandlesSearch.Add(newHandle, this.GraphicsBuffersHandles.Count);
                this.GraphicsBuffersHandles.Add(newHandle);
            }

            return (UInt16)this.GraphicsBuffersHandlesSearch[newHandle];
        }

        /// <summary>
        /// Method sets buffers.
        /// </summary>
        /// <param name="id"></param>
        public void SetBuffers(UInt16 id)
        {
            GraphicsBuffersHandle newHandle = this.GraphicsBuffersHandles[(int)id];
                        
            ShevaEngine.Instance.GraphicsDevice.SetVertexBuffer(this.VertexBuffers[newHandle.VboID]);
            ShevaEngine.Instance.GraphicsDevice.Indices = this.IndexBuffers[newHandle.VboID];
        }
    }    
}
